﻿using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Text;
using Windows.UI.Xaml;
using Windows.UI.Xaml.Controls;
using com.ddmresources.EnumMetadata.Core;
using com.ddmresources.EnumMetadata.Core.Attributes;
using com.ddmresources.EnumMetadata.Samples;

namespace com.ddmresources.EnumMetadata.Demo
{
    /// <summary>
    /// This class contains sample methods that demonstrate the feature of the EnumMetadata Library and how to use
    /// them. The methods depend on sample enums defined in the EnumMetadata.Samples dll. 
    /// 
    /// You can execute all these samples and see the output by having a Debug application project invoke
    /// EnumMetadataDemo.RunAll (or any subset you choose).
    /// 
    /// To see the source code for these enums, view the other class files in the Samples folder that contains this class.
    /// 
    /// Full source code and unit tests are available at
    /// http://EnumMetadata.codeplex.com
    /// </summary>
    public class EnumMetadataDemo
    {
        private TextBlock textBlock = null;
        private StringBuilder stringBuilder;

        public EnumMetadataDemo(TextBlock textBlock)
        {
            this.textBlock = textBlock;
            stringBuilder = new StringBuilder();
        }

        public void RunAll()
        {

            stringBuilder.AppendLine(
                "For full examples of how to use the EnumMetadataHelper API, see EnumMetadataDemo.cs and EnumMetadata.Test\\EnumMetadataTests.cs");
            stringBuilder.AppendLine();

            //Info Method usage           
            Info_Enum_Generic_Success();
            Info_Enum_StronglyTypedHelper_Success();
            InfoType_DynamicEnum_Generic_Success();
            InfoType_DynamicEnum_Generic_ChildArray_Success();
            InfoType_DynamicEnum_Generic_ChildObject_Success();
            Info_DynamicEnum_StronglyTypedHelper_Success();

            //Show failure modes for the Info Method
            Info_EnumInfoSpecificationMissing_Failure();
            Info_MissingMetadataAttributeTypeProperty_Failure();
            Info_MissingOutputTypeProperty_Failure();
            Info_NullEnumInstance_Failure();
            Info_InvalidInfoMode_Failure();
            Info_MissingDynamicInfoAttribute_Failure();

            //InfoLax Method usage (unique to InfoLax)
            InfoLax_NullEnumInstance_Success();
            InfoLax__BadEnumValue_Success();
            InfoLaxLax_Dynamic_BadEnumValue_Success();

            //GetEnumInstanceAttribute Method Usage
            GetEnumInstanceAttribute__FullInputs_Success();
            GetEnumInstanceAttribute__FilledNullable_Success();
            GetEnumInstanceAttribute_Dynamic_FullInputs_Success();
            GetEnumInstanceAttribute_Dynamic_FilledNullable_Success();

            //Show failure modes for the GetEnumInstanceAttribute Method
            GetEnumInstanceAttribute__EmptyNullable_Failure();
            GetEnumInstanceAttribute__NoSoughtType_Failure();
            GetEnumInstanceAttribute_Dynamic_EmptyNullable_Failure();
            GetEnumInstanceAttribute_Dynamic_NoSoughtType_Failure();

            //GetEnumInstanceAttributeLax Method Usage (unique to GetEnumInstanceAttributeLax)
            GetEnumInstanceAttributeLax__EmptyNullable_Success();
            GetEnumInstanceAttributeLax__BadEnumValue_Success();
            GetEnumInstanceAttributeLax_Dynamic_EmptyNullable_Success();
            GetEnumInstanceAttributeLax_Dynamic_BadEnumValue_Success();

            //GetEnumInstance Method Usage
            GetEnumInstance_Int_Success();
            GetEnumInstance_String_Success();
            //Show failure modes for GetEnumInstance Method
            GetEnumInstance_BadInt_Failure();            
            GetEnumInstance_BadString_Failure();

            //FindEnumInstances Usage
            FindEnumInstances_DynamicEnum_SingleMatch_Success();
            FindEnumInstances_DynamicEnum_MultipleMatch_Success();
            FindEnumInstances_DynamicEnum_NoMatch_GetBackEmptyEnumerable_Success();
            FindEnumInstances_Enum_SingleMatch_Success();
            FindEnumInstances_Enum_MultipleMatch_Success();
            FindEnumInstances_Enum_NoMatch_GetBackEmptyEnumerable_Success();

            //ExtractEnumList Usage
            ExtractEnumList_Enum_Success();
            ExtractEnumList_Enum_FromMatchList_Success();
            ExtractEnumList_DynamicEnum_Success();
            ExtractEnumList_DynamicEnum_FromMatchList_Success();
        }
        #region Info Method Usage

        public void Info_Enum_Generic_Success()
        {
            stringBuilder.AppendLine("**** Info method; generic parameter;  enum  ****");
            stringBuilder.AppendLine("usage: var result = CbiType.GA.Info<ICodeTableInfo>().Description;");

            var result = CbiType.GA.Info<ICodeTableInfo>().Description;

            stringBuilder.AppendLine("Result = " + result); //"Geographic Area"
            stringBuilder.AppendLine();
            textBlock.Text = stringBuilder.ToString();
        }

        public void Info_Enum_StronglyTypedHelper_Success()
        {
            stringBuilder.AppendLine("**** Info method; strongly typed helper;  enum ****");
            stringBuilder.AppendLine("usage: var result = HelpTopic.ConstructionView.Info().Id;");

            var result = HelpTopic.ConstructionView.Info().Id;

            stringBuilder.AppendLine("Result = " + result); //102
            stringBuilder.AppendLine();
            textBlock.Text = stringBuilder.ToString();
        }

        public void InfoType_DynamicEnum_Generic_Success()
        {
            stringBuilder.AppendLine("**** Info method; generic parameter; dynamic enum ****");
            stringBuilder.AppendLine("usage: var result = TrafficLightColor.Yellow.Info<ITrafficLightColorInfo>().Wavelength;");

            var result = TrafficLightColor.Yellow.Info<ITrafficLightColorInfo>().Wavelength;

            stringBuilder.AppendLine("Result = " + result); //570
            stringBuilder.AppendLine();
            textBlock.Text = stringBuilder.ToString();
        }

        public void InfoType_DynamicEnum_Generic_ChildArray_Success()
        {
            stringBuilder.AppendLine("**** Info method; generic parameter; dynamic enum; child array access ****");
            stringBuilder.AppendLine("usage: var result = TrafficLightColor.Yellow.Info<ITrafficLightColorInfo>().NTSBRegulations[1];");

            var result = TrafficLightColor.Yellow.Info<ITrafficLightColorInfo>().NTSBRegulations[1];

            stringBuilder.AppendLine("Result = " + result); //8
            stringBuilder.AppendLine();
            textBlock.Text = stringBuilder.ToString();
        }

        public void InfoType_DynamicEnum_Generic_ChildObject_Success()
        {
            stringBuilder.AppendLine("**** Info method; generic parameter; dynamic enum; child object access ****");
            stringBuilder.AppendLine("usage: var result = TrafficLightColor.Green.Info<ITrafficLightColorInfo>().Example.Id;");

            var result = TrafficLightColor.Green.Info<ITrafficLightColorInfo>().Example.Id;

            stringBuilder.AppendLine("Result = " + result); //103
            stringBuilder.AppendLine();
            textBlock.Text = stringBuilder.ToString();
        }

        public void Info_DynamicEnum_StronglyTypedHelper_Success()
        {
            stringBuilder.AppendLine("**** Info method; strongly typed helper; dynamic enum ****");
            stringBuilder.AppendLine("usage: var result = ClientStatus.Active.Info().Description;");

            var result = ClientStatus.Active.Info().Description;

            stringBuilder.AppendLine("Result = " + result); //"Active Status"
            stringBuilder.AppendLine();
            textBlock.Text = stringBuilder.ToString();
        }

        public void Info_EnumInfoSpecificationMissing_Failure()
        {
            stringBuilder.AppendLine("**** Info method; EnumInfoSpecification Missing; throws ****");

            string result;
            try
            {
                stringBuilder.AppendLine("usage: result = MissingEnumInfoSpecification.Value1.Info<IClientStatusInfo>().Code;");
                result = MissingEnumInfoSpecification.Value1.Info<IClientStatusInfo>().Code;
                stringBuilder.AppendLine("Result = " + result); //will never get here
            }
            catch (InvalidOperationException)
            {
                result = "InvalidOperationException thrown";
                stringBuilder.AppendLine("Result = " + result);
            }

            stringBuilder.AppendLine();
            textBlock.Text = stringBuilder.ToString();
        }

        public void Info_MissingMetadataAttributeTypeProperty_Failure()
        {
            stringBuilder.AppendLine("**** Info method; MetadataAttributeTypeProperty Missing; throws ****");
            string result;
            try
            {
                stringBuilder.AppendLine("usage: result = MissingMetadatAttributeTypeProperty.Value1.Info<IClientStatusInfo>().Code;");
                result = MissingMetadatAttributeTypeProperty.Value1.Info<IClientStatusInfo>().Code;
                stringBuilder.AppendLine("Result = " + result); //will never get here
            }
            catch (ArgumentException)
            {
                result = "ArgumentException thrown";
                stringBuilder.AppendLine("Result = " + result);
            }
            stringBuilder.AppendLine();
            textBlock.Text = stringBuilder.ToString();
        }

        public void Info_MissingOutputTypeProperty_Failure()
        {
            stringBuilder.AppendLine("**** Info method; MetadataOutputTypeProperty Missing; throws ****");
            string result;
            try
            {
                stringBuilder.AppendLine("usage: result = MissingMetadatAttributeTypeProperty.Value1.Info<IClientStatusInfo>().Code;");
                result = MissingMetadatAttributeTypeProperty.Value1.Info<IClientStatusInfo>().Code;
                stringBuilder.AppendLine("Result = " + result); //will never get here
            }
            catch (ArgumentException)
            {
                result = "ArgumentException thrown";
                stringBuilder.AppendLine("Result = " + result);
            }
            stringBuilder.AppendLine();
            textBlock.Text = stringBuilder.ToString();
        }

        public void Info_NullEnumInstance_Failure()
        {
            stringBuilder.AppendLine("**** Info method; Null enum instance; throws ****");
            Enum e = null;
            string result;
            try
            {
                stringBuilder.AppendLine("usage: result = e.Info<IClientStatusInfo>().Description;");
                result = e.Info<IClientStatusInfo>().Description;
                stringBuilder.AppendLine("Result = " + result); //will never get here
            }
            catch (ArgumentException)
            {
                result = "ArgumentException thrown";
                stringBuilder.AppendLine("Result = " + result);
            }
            stringBuilder.AppendLine();
            textBlock.Text = stringBuilder.ToString();
        }

        public void Info_InvalidInfoMode_Failure()
        {
            stringBuilder.AppendLine("**** Info method; Invalid InfoMode; throws ****");
            string result;
            try
            {
                stringBuilder.AppendLine("usage: result = InvalidInfoMode.Value1.Info<IClientStatusInfo>().Code;");
                result = InvalidInfoMode.Value1.Info<IClientStatusInfo>().Code;
                stringBuilder.AppendLine("Result = " + result); //will never get here
            }
            catch (ArgumentException)
            {
                result = "ArgumentException thrown";
                stringBuilder.AppendLine("Result = " + result);
            }
            stringBuilder.AppendLine();
            textBlock.Text = stringBuilder.ToString();
        }

        public void Info_MissingDynamicInfoAttribute_Failure()
        {
            stringBuilder.AppendLine("**** Info method; DynamicInfoAttribute Missing; throws ****");
            string result;
            try
            {
                stringBuilder.AppendLine("usage: result = MissingDynamicInfo.Value1.Info<IClientStatusInfo>().Code;");
                result = MissingDynamicInfo.Value1.Info<IClientStatusInfo>().Code;
                stringBuilder.AppendLine("Result = " + result); //will never get here
            }
            catch (InvalidOperationException)
            {
                result = "InvalidOperationException thrown";
                stringBuilder.AppendLine("Result = " + result);
            }
            stringBuilder.AppendLine();
            textBlock.Text = stringBuilder.ToString();
        } 
        #endregion

        #region Info Lax Method Usage
        //These methods detail areas where behavior is different for the InfoLax method from what the Info method does.
        //In all other usage scenarios, InfoLax is used just like Info and returns the same results.

        public  void InfoLax_NullEnumInstance_Success()
        {
            stringBuilder.AppendLine("**** InfoLax method; null enum;  enum  ****");

            stringBuilder.AppendLine("usage: var clientStatusInfo = e.InfoLax<ClientStatusInfo>();");

            Enum e = null;
            var clientStatusInfo = e.InfoLax<ClientStatusInfo>(); //blank new copy of requested metadata object
            var result = clientStatusInfo.Id;

            stringBuilder.AppendLine("Result = " + result); //0
            stringBuilder.AppendLine();
            textBlock.Text = stringBuilder.ToString();
        }

        public  void InfoLax__BadEnumValue_Success()
        {
            stringBuilder.AppendLine("**** InfoLax method; bad enum value;  enum  ****");

            stringBuilder.AppendLine("usage: see code");

            CbiType badCbi = EnumMetadataHelper.GetEnumInstance<CbiType>(999);

            var codeTableInfo = badCbi.InfoLax<CodeTableInfoAttribute>();
            var result = codeTableInfo.MappedId;

            stringBuilder.AppendLine("Result = " + result); //0
            stringBuilder.AppendLine();
            textBlock.Text = stringBuilder.ToString();
        }

        public  void InfoLaxLax_Dynamic_BadEnumValue_Success()
        {
            stringBuilder.AppendLine("**** InfoLax method; bad enum value; dynamic enum  ****");
            stringBuilder.AppendLine("usage: see code");

            ClientStatus badClientStatus = EnumMetadataHelper.GetEnumInstance<ClientStatus>(999);

            var clientStatusInfo = badClientStatus.InfoLax<ClientStatusInfo>();
            var result = clientStatusInfo.Id;

            stringBuilder.AppendLine("Result = " + result); //0
            stringBuilder.AppendLine();
            textBlock.Text = stringBuilder.ToString();
        }
        #endregion

        #region GetEnumInstanceAttribute Method Usage
        public  void  GetEnumInstanceAttribute__FullInputs_Success()
        {
            stringBuilder.AppendLine("**** GetEnumInstanceAttribute method; valid enum provided  ****");
            stringBuilder.AppendLine("usage: see code");

            var cbiType = CbiType.UBI;
            var codeTableInfo = (ICodeTableInfo)EnumMetadataHelper.GetEnumInstanceAttribute(cbiType, typeof(CodeTableInfoAttribute));
            var result = codeTableInfo.MappedId;

            stringBuilder.AppendLine("Result = " + result); //8
            stringBuilder.AppendLine();
            textBlock.Text = stringBuilder.ToString();
        }

        public  void  GetEnumInstanceAttribute__FilledNullable_Success()
        {
            stringBuilder.AppendLine("**** GetEnumInstanceAttribute method; valid enum provided in nullable property  ****");
            stringBuilder.AppendLine("usage: see code");

            var classWithNullableEnumProperty = new ClassWithNullableEnumProperty { Cbi = CbiType.UBI };
            var codeTableInfo = (ICodeTableInfo)EnumMetadataHelper.GetEnumInstanceAttribute(classWithNullableEnumProperty.Cbi, typeof(CodeTableInfoAttribute));
            var result = codeTableInfo.MappedId;

            stringBuilder.AppendLine("Result = " + result); //8
            stringBuilder.AppendLine();
            textBlock.Text = stringBuilder.ToString();
        }

        public  void GetEnumInstanceAttribute__EmptyNullable_Failure() 
        {
            stringBuilder.AppendLine("**** GetEnumInstanceAttribute method; Null enum provided in nullable property; throws ****");
            stringBuilder.AppendLine("usage: see code");

            var classWithNullableEnumProperty = new ClassWithNullableEnumProperty { Cbi = null };
            string result = String.Empty;

            try
            {
                var codeTableInfo = (ICodeTableInfo)EnumMetadataHelper.GetEnumInstanceAttribute(classWithNullableEnumProperty.Cbi, typeof(CodeTableInfoAttribute));
                stringBuilder.AppendLine("Result = " + result); //will never get here
            }
            catch (ArgumentException)
            {
                result = "ArgumentException thrown";
                stringBuilder.AppendLine("Result = " + result);
            }
            stringBuilder.AppendLine();
            textBlock.Text = stringBuilder.ToString();
        }

        public  void  GetEnumInstanceAttribute__NoSoughtType_Failure()
        {
            stringBuilder.AppendLine("**** GetEnumInstanceAttribute method; no output type provided; throws ****");
            stringBuilder.AppendLine("usage: see code");

            var classWithNullableEnumProperty = new ClassWithNullableEnumProperty { Cbi = CbiType.UBI };
            string result = String.Empty;

            try
            {
                var codeTableInfo = (ICodeTableInfo)EnumMetadataHelper.GetEnumInstanceAttribute(classWithNullableEnumProperty.Cbi, null); 
                stringBuilder.AppendLine("Result = " + result); //will never get here
            }
            catch (ArgumentException)
            {
                result = "ArgumentException thrown";
                stringBuilder.AppendLine("Result = " + result);
            }
            stringBuilder.AppendLine();
            textBlock.Text = stringBuilder.ToString();
        }

        public  void GetEnumInstanceAttribute_Dynamic_FullInputs_Success()
        {
            stringBuilder.AppendLine("**** GetEnumInstanceAttribute method; dynamic; valid inputs provided  ****");
            stringBuilder.AppendLine("usage: see code");

            var clientStatus = ClientStatus.Active;
            var enumDynamicInfoAttribute = (EnumDynamicInfoAttribute)EnumMetadataHelper.GetEnumInstanceAttribute(clientStatus, typeof(EnumDynamicInfoAttribute));

            var result = enumDynamicInfoAttribute.Info; 

            stringBuilder.AppendLine("Result = " + result); // @"{""Id"": 11, ""Code"":""A"", ""Description"":""Active Status"", ""IsMapped"": true}"
            stringBuilder.AppendLine();
            textBlock.Text = stringBuilder.ToString();
        }

        public  void GetEnumInstanceAttribute_Dynamic_FilledNullable_Success()
        {
            stringBuilder.AppendLine("**** GetEnumInstanceAttribute method; dynamic; filled nullable enum prop provided  ****");
            stringBuilder.AppendLine("usage: see code");

            var classWithNullableEnumProperty = new ClassWithNullableEnumProperty { ClientStatus = ClientStatus.Active };
            var enumDynamicInfoAttribute = (EnumDynamicInfoAttribute)EnumMetadataHelper.GetEnumInstanceAttribute(classWithNullableEnumProperty.ClientStatus, typeof(EnumDynamicInfoAttribute));
            var result = enumDynamicInfoAttribute.Info;//@"{""Id"": 11, ""Code"":""A"", ""Description"":""Active Status"", ""IsMapped"": true}");

            stringBuilder.AppendLine("Result = " + result); //UBI
            stringBuilder.AppendLine();
            textBlock.Text = stringBuilder.ToString();
        }

        public  void GetEnumInstanceAttribute_Dynamic_EmptyNullable_Failure()
        {
            stringBuilder.AppendLine("**** GetEnumInstanceAttribute method; dynamic; Null enum provided in nullable property; throws ****");
            stringBuilder.AppendLine("usage: see code");

            var classWithNullableEnumProperty = new ClassWithNullableEnumProperty { ClientStatus = null };
            string result = String.Empty;

            try
            {                
                var enumDynamicInfoAttribute = (EnumDynamicInfoAttribute)EnumMetadataHelper.GetEnumInstanceAttribute(classWithNullableEnumProperty.ClientStatus, typeof(EnumDynamicInfoAttribute));
                stringBuilder.AppendLine("Result = " + result); //will never get here
            }
            catch (ArgumentException)
            {
                result = "ArgumentException thrown";
                stringBuilder.AppendLine("Result = " + result);
            }
            stringBuilder.AppendLine();
            textBlock.Text = stringBuilder.ToString();
        }

        public  void GetEnumInstanceAttribute_Dynamic_NoSoughtType_Failure()
        {
            stringBuilder.AppendLine("**** GetEnumInstanceAttribute method; dynamic; no output type provided; throws ****");
            stringBuilder.AppendLine("usage: see code");

            var classWithNullableEnumProperty = new ClassWithNullableEnumProperty { ClientStatus = ClientStatus.Active };
            string result = String.Empty;

            try
            {
                var enumDynamicInfoAttribute = (EnumDynamicInfoAttribute)EnumMetadataHelper.GetEnumInstanceAttribute(classWithNullableEnumProperty.ClientStatus, null);
                stringBuilder.AppendLine("Result = " + result); //will never get here
            }
            catch (ArgumentException)
            {
                result = "ArgumentException thrown";
                stringBuilder.AppendLine("Result = " + result);
            }
            stringBuilder.AppendLine();
            textBlock.Text = stringBuilder.ToString();
        }

        #endregion

        #region GetEnumInstanceAttributeLax Method Usage
        //These methods detail areas where behavior is different for the GetEnumInstanceAttributeLax method from
        //what the GetEnumInstanceAttribute method does.
        //In all other usage scenarios, GetEnumInstanceAttributeLax is used just like GetEnumInstanceAttribute and returns the same results.
  
        public  void GetEnumInstanceAttributeLax__EmptyNullable_Success()
        {
            stringBuilder.AppendLine("**** GetEnumInstanceAttributeLax method; empty nullable enum prop provided  ****");
            stringBuilder.AppendLine("usage: see code");

            var classWithNullableEnumProperty = new ClassWithNullableEnumProperty { Cbi = null };
            var codeTableInfo = (ICodeTableInfo)EnumMetadataHelper.GetEnumInstanceAttributeLax(classWithNullableEnumProperty.Cbi, typeof(CodeTableInfoAttribute));
            var result = codeTableInfo.MappedId;

            stringBuilder.AppendLine("Result = " + result); //0
            stringBuilder.AppendLine();
            textBlock.Text = stringBuilder.ToString();
        }

        public  void GetEnumInstanceAttributeLax__BadEnumValue_Success()
        {
            stringBuilder.AppendLine("**** GetEnumInstanceAttribute method; invalid enum provided  ****");
            stringBuilder.AppendLine("usage: see code");

            CbiType badCbi = EnumMetadataHelper.GetEnumInstance<CbiType>(999);
            var classWithNullableEnumProperty = new ClassWithNullableEnumProperty() { Cbi = badCbi };

            var codeTableInfo = (ICodeTableInfo)EnumMetadataHelper.GetEnumInstanceAttributeLax(classWithNullableEnumProperty.Cbi, typeof(CodeTableInfoAttribute));
            var result = codeTableInfo.MappedId;

            stringBuilder.AppendLine("Result = " + result); //0
            stringBuilder.AppendLine();
            textBlock.Text = stringBuilder.ToString();
        }

        public  void GetEnumInstanceAttributeLax_Dynamic_EmptyNullable_Success()
        {
            stringBuilder.AppendLine("**** GetEnumInstanceAttribute method; dynamic;null enum provided  ****");
            stringBuilder.AppendLine("usage: see code");

            var classWithNullableEnumProperty = new ClassWithNullableEnumProperty { ClientStatus = null };
            var enumDynamicInfoAttribute = (EnumDynamicInfoAttribute)EnumMetadataHelper.GetEnumInstanceAttributeLax(classWithNullableEnumProperty.ClientStatus, typeof(EnumDynamicInfoAttribute));
            var result = enumDynamicInfoAttribute.Info;

            stringBuilder.AppendLine("Result = " + result); //null
            stringBuilder.AppendLine();
            textBlock.Text = stringBuilder.ToString();
        }

        public  void GetEnumInstanceAttributeLax_Dynamic_BadEnumValue_Success()
        {
            stringBuilder.AppendLine("**** GetEnumInstanceAttribute method; dynamic;  invalid enum provided  ****");
            stringBuilder.AppendLine("usage: see code");

            ClientStatus badClientStatus = EnumMetadataHelper.GetEnumInstance<ClientStatus>(999);
            var classWithNullableEnumProperty = new ClassWithNullableEnumProperty() { ClientStatus = badClientStatus };
            var enumDynamicInfoAttribute = (EnumDynamicInfoAttribute)EnumMetadataHelper.GetEnumInstanceAttributeLax(classWithNullableEnumProperty.ClientStatus, typeof(EnumDynamicInfoAttribute));
            var result = enumDynamicInfoAttribute.Info;

            stringBuilder.AppendLine("Result = " + result); //null
            stringBuilder.AppendLine();
            textBlock.Text = stringBuilder.ToString();
        }

  
        #endregion

        #region GetEnumInstance Usage

        public  void GetEnumInstance_Int_Success()
        {
            stringBuilder.AppendLine("**** GetEnumInstance method; valid int provided  ****");
            stringBuilder.AppendLine("usage: var result = EnumMetadataHelper.GetEnumInstance<CbiType>(8);");

            var result = EnumMetadataHelper.GetEnumInstance<CbiType>(8);

            stringBuilder.AppendLine("Result = " + result); //UBI
            stringBuilder.AppendLine();
            textBlock.Text = stringBuilder.ToString();
        }

        public  void GetEnumInstance_String_Success()
        {
            stringBuilder.AppendLine("**** GetEnumInstance method; valid string provided  ****");
            stringBuilder.AppendLine("usage: var result = EnumMetadataHelper.GetEnumInstance<TrafficLightColor>(\"Green\");");

            var result = EnumMetadataHelper.GetEnumInstance<TrafficLightColor>("Green");

            stringBuilder.AppendLine("Result = " + result); //Green
            stringBuilder.AppendLine();
            textBlock.Text = stringBuilder.ToString();
        }

        public  void GetEnumInstance_BadInt_Failure()
        {
            stringBuilder.AppendLine("**** GetEnumInstance method; invalid int provided; returns -1 ****");
            stringBuilder.AppendLine("usage: var result = EnumMetadataHelper.GetEnumInstance<CbiType>(1000);");

            var result = EnumMetadataHelper.GetEnumInstance<CbiType>(1000);
            stringBuilder.AppendLine("Result = " + result); //marker value of -1

            stringBuilder.AppendLine();
            textBlock.Text = stringBuilder.ToString();
        }

        public  void GetEnumInstance_BadString_Failure()
        {
            stringBuilder.AppendLine("**** GetEnumInstance method; invalid string provided; returns -1 ****");
            stringBuilder.AppendLine("usage: var result = EnumMetadataHelper.GetEnumInstance<TrafficLightColor>(\"BadInput\");");

            var result = EnumMetadataHelper.GetEnumInstance<TrafficLightColor>("BadInput");
            stringBuilder.AppendLine("Result = " + result); //marker value of -1

            stringBuilder.AppendLine();
            textBlock.Text = stringBuilder.ToString();
        }
        #endregion

        #region FindEnumInstances Usage

        public  void FindEnumInstances_DynamicEnum_SingleMatch_Success()
        {
            stringBuilder.AppendLine("**** FindEnumInstances method; dynamic enum; single match  ****");
            stringBuilder.AppendLine("usage: var result = EnumMetadataHelper.FindEnumInstances<TrafficLightColor, ITrafficLightColorInfo, int>(() => (new TrafficLightColorInfo()).Wavelength, 650);");

            var result = EnumMetadataHelper.FindEnumInstances<TrafficLightColor, ITrafficLightColorInfo, int>(
                () => (new TrafficLightColorInfo()).Wavelength, 650);

            stringBuilder.AppendLine("Matches = " + result.Count()); //1
            stringBuilder.AppendLine("First Match = " + result.First()); //Red
            stringBuilder.AppendLine();
            textBlock.Text = stringBuilder.ToString();
        }

        public  void FindEnumInstances_DynamicEnum_MultipleMatch_Success()
        {
            stringBuilder.AppendLine("**** FindEnumInstances method; dynamic enum, multiple matches  ****");
            stringBuilder.AppendLine("usage: var result = EnumMetadataHelper.FindEnumInstances<ClientStatus, IClientStatusInfo, bool>(() => (new ClientStatusInfo()).IsMapped, true);");

            var result = EnumMetadataHelper.FindEnumInstances<ClientStatus, IClientStatusInfo, bool>(() => (new ClientStatusInfo()).IsMapped, true);

            stringBuilder.AppendLine("Matches = " + result.Count()); //2
            stringBuilder.AppendLine("First Match = " + result.ElementAt(0)); //Active
            stringBuilder.AppendLine("Second Match = " + result.ElementAt(1)); //Inactive
            stringBuilder.AppendLine();
            textBlock.Text = stringBuilder.ToString();
        }

        public  void FindEnumInstances_DynamicEnum_NoMatch_GetBackEmptyEnumerable_Success()
        {
            stringBuilder.AppendLine("**** FindEnumInstances method; dynamic enum; no match  ****");
            stringBuilder.AppendLine("usage: var result = EnumMetadataHelper.FindEnumInstances<TrafficLightColor, ITrafficLightColorInfo, int>(() => (new TrafficLightColorInfo()).Wavelength, -99);");


            var result = EnumMetadataHelper.FindEnumInstances<TrafficLightColor, ITrafficLightColorInfo, int>(
                () => (new TrafficLightColorInfo()).Wavelength, -99);

            stringBuilder.AppendLine("Result is enum = " + (result is IEnumerable ? true : false)); //true
            stringBuilder.AppendLine("Matches = " + result.Count()); //0
            
            stringBuilder.AppendLine();
            textBlock.Text = stringBuilder.ToString();
        }

        public  void FindEnumInstances_Enum_SingleMatch_Success()
        {
            stringBuilder.AppendLine("**** FindEnumInstances method;  enum; single match  ****");
            stringBuilder.AppendLine("usage: var result = EnumMetadataHelper.FindEnumInstances<CbiType, ICodeTableInfo, string>(() => (new CodeTableInfoAttribute()).MappedCode, \"NL\");");

            var result = EnumMetadataHelper.FindEnumInstances<CbiType, ICodeTableInfo, string>(
                () => (new CodeTableInfoAttribute()).MappedCode, "NL");

            stringBuilder.AppendLine("Matches = " + result.Count()); //1
            stringBuilder.AppendLine("First Match = " + result.First()); //NL
            stringBuilder.AppendLine();
            textBlock.Text = stringBuilder.ToString();
        }

        public  void FindEnumInstances_Enum_MultipleMatch_Success()
        {
            stringBuilder.AppendLine("**** FindEnumInstances method;  enum, multiple matches  ****");
            stringBuilder.AppendLine("usage: var result = EnumMetadataHelper.FindEnumInstances<HelpTopic, IHelpTopicInfo, bool>(() => (new HelpTopicInfoAttribute()).IsContentCrossCompany, true);");

            var result = EnumMetadataHelper.FindEnumInstances<HelpTopic, IHelpTopicInfo, bool>(() => (new HelpTopicInfoAttribute()).IsContentCrossCompany, true);

            stringBuilder.AppendLine("Matches = " + result.Count()); //2
            stringBuilder.AppendLine("First Match = " + result.ElementAt(0)); //AccountView
            stringBuilder.AppendLine("Second Match = " + result.ElementAt(1)); //LocationsView
            stringBuilder.AppendLine();
            textBlock.Text = stringBuilder.ToString();
        }

        public  void FindEnumInstances_Enum_NoMatch_GetBackEmptyEnumerable_Success()
        {
            stringBuilder.AppendLine("**** FindEnumInstances method;  enum; no match  ****");
            stringBuilder.AppendLine("usage: var result = EnumMetadataHelper.FindEnumInstances<HelpTopic, IHelpTopicInfo, string>(() => (new HelpTopicInfoAttribute()).SkinName, \"BadData\");");

            var result = EnumMetadataHelper.FindEnumInstances<HelpTopic, IHelpTopicInfo, string>(() => (new HelpTopicInfoAttribute()).SkinName, "BadData");

            stringBuilder.AppendLine("Result is enum = " + (result is IEnumerable ? true : false)); //true
            stringBuilder.AppendLine("Matches = " + result.Count()); //0

            stringBuilder.AppendLine();
            textBlock.Text = stringBuilder.ToString();
        }
        #endregion

        #region ExtractEnumList Usage

        public  void ExtractEnumList_Enum_Success()
        {
            stringBuilder.AppendLine("**** ExtractEnumList method;  enum, source is full enum  ****");
            stringBuilder.AppendLine("usage: see code");

            var comboList =
                EnumMetadataHelper.ExtractEnumList<CbiType, ICodeTableInfo, string>(() => (new CodeTableInfoAttribute()).Description);

            var description = (comboList.Where(kvp => kvp.Key == CbiType.UBI).Single()).Value;

            stringBuilder.AppendLine("Result = " + description); //"Unreported Business Interest"
            stringBuilder.AppendLine();
            textBlock.Text = stringBuilder.ToString();
        }

        public  void ExtractEnumList_Enum_FromMatchList_Success()
        {
            stringBuilder.AppendLine("**** ExtractEnumList method;  enum, source is filtered list   ****");
            stringBuilder.AppendLine("usage: see code");

            var matchList =
                EnumMetadataHelper.FindEnumInstances<HelpTopic, IHelpTopicInfo, bool>(() => (new HelpTopicInfoAttribute()).IsContentCrossCompany, false);

            var comboList =
                EnumMetadataHelper.ExtractEnumList<HelpTopic, IHelpTopicInfo, string>(
                    () => (new HelpTopicInfoAttribute()).Id, matchList);

            var id = (comboList.Where(kvp => kvp.Key == HelpTopic.EngineeringView).Single()).Value;

            stringBuilder.AppendLine("Matches = " + comboList.Count); //2
            stringBuilder.AppendLine("First Match = " + comboList.ElementAt(0).Key); //EngineeringView
            stringBuilder.AppendLine("Second Match = " + comboList.ElementAt(1).Key); //ConstructionView
            stringBuilder.AppendLine("Display Value of First Match = " + id); //101
            stringBuilder.AppendLine();
            textBlock.Text = stringBuilder.ToString();
        }

        public  void ExtractEnumList_DynamicEnum_Success()
        {
            stringBuilder.AppendLine("**** ExtractEnumList method; dynamic enum  ****");
            stringBuilder.AppendLine("usage: see code");

            var comboList =
                EnumMetadataHelper.ExtractEnumList<TrafficLightColor, ITrafficLightColorInfo, string>(() => (new TrafficLightColorInfo()).IntendedAction);

            var description = (comboList.Where(kvp => kvp.Key == TrafficLightColor.Green).Single()).Value;

            stringBuilder.AppendLine("Result = " + description); //"Proceed"
            stringBuilder.AppendLine();
            textBlock.Text = stringBuilder.ToString();
        }

        public  void ExtractEnumList_DynamicEnum_FromMatchList_Success()
        {
            stringBuilder.AppendLine("**** ExtractEnumList method; dynamic enum, source is filtered list   ****");
            stringBuilder.AppendLine("usage: see code");

            var matchList =
                EnumMetadataHelper.FindEnumInstances<TrafficLightColor, ITrafficLightColorInfo, bool>(() => (new TrafficLightColorInfo()).IsColorBlind, true);

            var comboList =
                EnumMetadataHelper.ExtractEnumList<TrafficLightColor, ITrafficLightColorInfo, string>(
                    () => (new TrafficLightColorInfo()).IntendedAction, matchList);

            var intendedAction = (comboList.Where(kvp => kvp.Key == TrafficLightColor.Green).Single()).Value;

            stringBuilder.AppendLine("Matches = " + comboList.Count); //1
            stringBuilder.AppendLine("First Match = " + comboList.ElementAt(0).Key); //Green
            stringBuilder.AppendLine("Display Value of First Match = " + intendedAction); //Proceed
            stringBuilder.AppendLine();
            textBlock.Text = stringBuilder.ToString();
        }
        #endregion

        #region Utility Classes
        public class ClassWithNullableEnumProperty
        {
            public Nullable<CbiType> Cbi { get; set; }
            public Nullable<ClientStatus> ClientStatus { get; set; }
        }

        #endregion
    }
}
